package com.ly.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.annotation.DataScope;
import com.ly.common.constant.UserConstants;
import com.ly.common.core.domain.entity.SysMenu;
import com.ly.common.core.domain.entity.SysRole;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.system.domain.SysRoleDept;
import com.ly.system.domain.SysRoleMenu;
import com.ly.system.mapper.*;
import com.ly.system.service.ISysMenuService;
import com.ly.system.service.ISysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 角色 业务层处理
 * @author ruoyi
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Resource
    private SysRoleMapper roleMapper;

    @Resource
    private SysRoleMenuMapper roleMenuMapper;

    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysRoleDeptMapper roleDeptMapper;

    @Resource
    private ISysMenuService menuService;

    /**
     * 根据条件分页查询角色数据
     * @param role 角色信息
     * @return 角色数据集合信息
     */
    @Override
    @DataScope (deptAlias = "d")
    public List<SysRole> selectRoleList (SysRole role) {
        return roleMapper.selectRoleList ( role );
    }

    /**
     * 根据用户ID查询权限
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectRolePermissionByUserId (String userId) {
        List<SysRole> perms = roleMapper.selectRolePermissionByUserId ( userId );
        Set<String> permsSet = new HashSet<> ();
        for ( SysRole perm : perms ) {
            if ( StringUtils.isNotNull ( perm ) ) {
                permsSet.addAll ( Arrays.asList ( perm.getRoleKey ().trim ().split ( "," ) ) );
            }
        }
        return permsSet;
    }

    /**
     * 查询所有角色
     * @return 角色列表
     */
    @Override
    public List<SysRole> selectRoleAll () {
        return SpringUtils.getAopProxy ( this ).selectRoleList ( new SysRole () );
    }

    /**
     * 根据用户ID获取角色选择框列表
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public List<String> selectRoleListByUserId (String userId) {
        return roleMapper.selectRoleListByUserId ( userId );
    }

    /**
     * 通过角色ID查询角色
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    @Override
    public SysRole selectRoleById (String roleId) {
        return roleMapper.selectRoleById ( roleId );
    }

    /**
     * 校验角色名称是否唯一
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public String checkRoleNameUnique (SysRole role) {
        String roleId = StringUtils.isNull ( role.getRoleId () ) ? "-1" : role.getRoleId ();
        SysRole info = roleMapper.checkRoleNameUnique ( role.getRoleName () );
        if ( StringUtils.isNotNull ( info ) && ! info.getRoleId ().equals ( roleId ) ) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色权限是否唯一
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public String checkRoleKeyUnique (SysRole role) {
        String roleId = StringUtils.isNull ( role.getRoleId () ) ? "-1" : role.getRoleId ();
        SysRole info = roleMapper.checkRoleKeyUnique ( role.getRoleKey () );
        if ( StringUtils.isNotNull ( info ) && ! info.getRoleId ().equals ( roleId ) ) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色是否允许操作
     * @param role 角色信息
     */
    @Override
    public void checkRoleAllowed (SysRole role) {
        if ( StringUtils.isNotNull ( role.getRoleId () ) && role.isAdmin () ) {
            throw new CustomException ( "不允许操作超级管理员角色" );
        }
    }

    /**
     * 通过角色ID查询角色使用数量
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public int countUserRoleByRoleId (String roleId) {
        return userRoleMapper.countUserRoleByRoleId ( roleId );
    }

    /**
     * 新增保存角色信息
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertRole (SysRole role) {
        // 新增角色信息
        role.setRoleId ( SnowflakeIdWorker.getInstance ().nextStringId () );
        role.setCreateTime ( DateUtils.getNowDate () );
        roleMapper.insertRole ( role );
        return insertRoleMenu ( role );
    }

    /**
     * 修改保存角色信息
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateRole (SysRole role) {
        // 修改角色信息
        roleMapper.updateRole ( role );
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId ( role.getRoleId () );
        return insertRoleMenu ( role );
    }

    /**
     * 修改角色状态
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public int updateRoleStatus (SysRole role) {
        return roleMapper.updateRole ( role );
    }

    /**
     * 修改数据权限信息
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int authDataScope (SysRole role) {
        // 修改角色信息
        roleMapper.updateRole ( role );
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId ( role.getRoleId () );
        // 新增角色和部门信息（数据权限）
        return insertRoleDept ( role );
    }

    /**
     * 新增角色菜单信息
     * @param role 角色对象
     */
    public int insertRoleMenu (SysRole role) {
        int rows = 1;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<SysRoleMenu> ();
        //判断role.getMenuIds()数组不为空
        if ( role.getMenuIds () != null && role.getMenuIds ().length > 0 ) {
            List<SysMenu> sysMenus = menuService.listByIds(Arrays.asList(role.getMenuIds()));
            //过滤出已选择的菜单
            List<SysMenu> sysMenuList = sysMenus.stream().filter(sysMenu -> "C".equals(sysMenu.getMenuType())).collect(Collectors.toList());
            List<SysMenu> menus = menuService.list(new LambdaQueryWrapper<SysMenu>()
                    .in(SysMenu::getHideRouteParentMenu, sysMenuList.stream().map(SysMenu::getMenuId).collect(Collectors.toList()))
                    .eq(SysMenu::getHideRoute, "0")
                    .eq(SysMenu::getMenuType, "C")
            );
            if (CollectionUtil.isNotEmpty(menus)) {
                for (SysMenu sysMenu : menus) {
                    SysRoleMenu rm = new SysRoleMenu();
                    rm.setRoleId(role.getRoleId());
                    rm.setMenuId(sysMenu.getMenuId());
                    list.add(rm);
                }
            }
        }
        for ( String menuId : role.getMenuIds () ) {
            SysRoleMenu rm = new SysRoleMenu ();
            rm.setRoleId ( role.getRoleId () );
            rm.setMenuId ( menuId );
            list.add ( rm );
        }




        if ( list.size () > 0 ) {
            rows = roleMenuMapper.batchRoleMenu ( list );
        }
        return rows;
    }

    /**
     * 新增角色部门信息(数据权限)
     * @param role 角色对象
     */
    public int insertRoleDept (SysRole role) {
        int rows = 1;
        // 新增角色与部门（数据权限）管理
        List<SysRoleDept> list = new ArrayList<SysRoleDept> ();
        for ( String deptId : role.getDeptIds () ) {
            SysRoleDept rd = new SysRoleDept ();
            rd.setRoleId ( role.getRoleId () );
            rd.setDeptId ( deptId );
            list.add ( rd );
        }
        if ( list.size () > 0 ) {
            rows = roleDeptMapper.batchRoleDept ( list );
        }
        return rows;
    }

    /**
     * 通过角色ID删除角色
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public int deleteRoleById (String roleId) {
        return roleMapper.deleteRoleById ( roleId );
    }

    /**
     * 批量删除角色信息
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @Override
    public int deleteRoleByIds (String[] roleIds) {
        for ( String roleId : roleIds ) {
            checkRoleAllowed ( new SysRole ( roleId ) );
            SysRole role = selectRoleById ( roleId );
            if ( countUserRoleByRoleId ( roleId ) > 0 ) {
                throw new CustomException ( String.format ( "%1$s已分配,不能删除", role.getRoleName () ) );
            }
        }
        return roleMapper.deleteRoleByIds ( roleIds );
    }
}
